package com.zretc.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.zretc.common.constant.SecurityConstant;
import com.zretc.common.constant.WebConstant;
import com.zretc.common.entity.R;
import com.zretc.common.entity.RespResult;
import com.zretc.common.util.JwtUtil;
import com.zretc.common.util.StringUtils;
import com.zretc.gateway.propertires.IgnoreWhileListProperties;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Objects;

@Component
public class AuthenticationFilter implements GlobalFilter, Ordered {
    @Autowired
    private IgnoreWhileListProperties ignoreWhileListProperties;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpRequest.Builder mutate = request.mutate();
        //获得请求URI
        String url = request.getURI().getPath();
        //获得白名单
        List<String> whiteList = ignoreWhileListProperties.getWhites();
        //删除可能存在的白名单header
        removeHeader(mutate ,SecurityConstant.WHITE_HEADER_NAME);
        //验证请求是否在白名单当中
        if(!Objects.isNull(whiteList) && !whiteList.isEmpty() && StringUtils.matches(url,whiteList)){
            //如果请求地址在白名单中----在请求头中 添加白名单字段
            mutate.header(SecurityConstant.WHITE_HEADER_NAME,SecurityConstant.WHITE_HEADER_NAME);
            return chain.filter(exchange);
        }
        //获得token
        String token = getToken(request);

        //判断令牌是否为空
        if(StringUtils.isEmpty(token)){
            //如果token为空 直接相应对应错误消息
            return unAuthenticationResp(exchange, WebConstant.TOKEN_NULL);
        }

        //解析jwt
        String key = null;

        try {
            Claims claims = JwtUtil.parseJWT(token);
            key = claims.getSubject();
        } catch (Exception e) {
           e.printStackTrace();
           //解析JWT过程出现异常 说明token非法或超时 直接返回错误消息
            return unAuthenticationResp(exchange, WebConstant.TOKEN_ERROR);
        }

        //判断key是否为空
        if(StringUtils.isEmpty(key)){
            return unAuthenticationResp(exchange, WebConstant.TOKEN_FAILED);
        }
        //验证通过 下发请求之前 携带Header
        mutate.header(SecurityConstant.AUTHENTICATION_KEY, key);
        //放行请求
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    //传入请求，删除请求头中对应参数
    private void removeHeader(ServerHttpRequest.Builder mutate,String name){
        mutate.headers(httpHeaders -> httpHeaders.remove(name));
    }
    //从请求头中 获得并返回token
    private String getToken(ServerHttpRequest request){
        return request.getHeaders().getFirst(SecurityConstant.AUTHENTICATION_HEADER_NAME);
    }
    //直接返回响应数据
    private Mono<Void> unAuthenticationResp(ServerWebExchange exchange,String msg){
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.OK);//返回200
        response.getHeaders().add("Content-Type","application/json");
        RespResult fail = R.fail(HttpStatus.UNAUTHORIZED.value(), msg);

        DataBuffer wrap = response.bufferFactory().wrap(JSON.toJSONString(fail).getBytes());

        return response.writeWith(Mono.just(wrap));

    }
}
